home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
daymisckit_proj
/
daymisckit-1
/
DAYLogFile.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
5KB
|
223 lines
//
// DAYLockFile.h -- a generic class to simplify keeping an atomic lock file
// Written by Don Yacktman (c) 1993 by Don Yacktman.
// Version 1.0. All rights reserved.
//
// This is a free object! Contact the author for the latest version.
// Don Yacktman, 4279 N. Ivy Lane, Provo, UT, 84604
// e-mail: Don_Yacktman@byu.edu
//
// You may use and copy this class freely as long as you
// comply with the following terms:
// (1) Do not remove the author's name or any of the
// copyright notices from this file.
// (2) If you redistribute an application which uses this
// object, you must either include the source code for
// this object with the application or state in your
// application's documentation that you (a) use this
// object and (b) where to obtain the source code for
// the object.
// (3) In no way shall the author or his employer(s) be held
// responsible for any damages caused by what this object
// does or does not do.
// (4) You have no warranty whatsoever that this object is
// good for any purpose at all. If you find it useful
// for something, consider yourself lucky and leave it at that.
//
// ***** denotes an unfinished/unimplemented method.
#import <daymisckit/daymisckit.h>
#import <stdio.h>
@interface DAYLogFile(private)
- _newLine; // forces the log to start without any history.
- _printRepeats; // "Last line repeated x times."
@end
@implementation DAYLogFile
- init
{
id ret = [super init];
fileOpen = NO; special = NO;
return ret;
}
- fileName { return fileName; }
- setFileName:aString
{
if (fileOpen) [self closeFile];
[lockFile free];
lockFile = nil;
special = NO;
fileName = aString;
return self;
}
- setLockFile:newLockFile
{
[lockFile free];
lockFile = newLockFile;
return self;
}
- (BOOL)addLineToLogFile:aString
{
if (![self openFile]) return NO;
if (![self appendToLogFile:aString andFlush:NO]) return NO;
if (![self closeFile]) return NO;
return YES;
}
- _newLine // forces the log to start without any history.
{
repeats = 0;
if (lastLine) {
[lastLine free]; lastLine = nil;
}
return self;
}
- (BOOL)openFile
{
if (special) return YES; // stdin and stdout are open already
if (fileOpen) return YES; // file is already open
if (lockFile) if (![lockFile lock]) return NO; // lock if needed
file = fopen([fileName stringValue], "a"); // do the open
if (!file) return NO;
fileOpen = YES;
[self _newLine];
return YES;
}
- (BOOL)closeFile
{
if (special) return YES; // don't close stdin or stdout
if (!fileOpen) return NO; // can't close an unopened file
[self _printRepeats];
fclose(file);
if (lockFile) if (![lockFile unlock]) return NO; // unlock if needed
fileOpen = NO;
return YES;
}
- _printRepeats
{
if (repeats) {
fprintf(file, "Last line repeated %d time%s\n", repeats,
((repeats == 1) ? "." : "s."));
}
[self _newLine];
return self;
}
- (BOOL)appendToLogFile:aString andFlush:(BOOL)flushFlag
{
if (!fileOpen) return NO;
// if the file is open, then we should have the lock.
// however, the user can get around our mechanism if they want, so
// we'd best check anyway, just to be sure.
if (lockFile && !special) if (![lockFile haveLock]) return NO;
// flushing will force a write; not flushing allows us to "compress"
// log messages by printing only number of repeats.
if (lastLine && !flushFlag) { // have a previous line, see if it repeats...
if ([lastLine isEqual:aString]) { // same as before
repeats++;
return YES; // don't print; keep tallying
} }
// if got here, the log line is different than last time.
[self _printRepeats];
fprintf(file, "%s", [aString stringValue]);
lastLine = [aString copy];
if (flushFlag) if (fflush(file) == EOF) return NO;
return YES;
}
- usestdout
{
[self setFileName:[[DAYString alloc] initString:"stdout"]];
special = YES;
fileOpen = YES;
file = stdout;
return self;
}
- usestderr
{
[self setFileName:[[DAYString alloc] initString:"stderr"]];
special = YES;
fileOpen = YES;
file = stderr;
return self;
}
- (FILE *)file { if (fileOpen) return file; else return NULL; }
- (BOOL)fileIsOpen { return fileOpen; }
- (BOOL)special { return special; }
- lockFile { return lockFile; }
- copy
{ // copies do not have locks or open logs... only original can!
id myCopy = [[DAYLogFile alloc] init];
[myCopy setFileName:fileName];
[myCopy setLockFile:[lockFile copy]];
return myCopy;
}
- read:(NXTypedStream *)stream
{
[super read:stream];
fileName = NXReadObject(stream);
lockFile = NXReadObject(stream);
return self;
}
- write:(NXTypedStream *)stream
{
[super write:stream];
NXWriteObject(stream, fileName);
NXWriteObject(stream, lockFile);
return self;
}
// NXTransport protocol implementation:
- encodeUsing:(id <NXEncoding>)portal
{
[portal encodeObjectBycopy:fileName];
[portal encodeObjectBycopy:lockFile];
return self;
}
- decodeUsing:(id <NXDecoding>)portal
{
fileName = [portal decodeObject];
lockFile = [portal decodeObject];
return self;
}
- encodeRemotelyFor:(NXConnection *)connection
freeAfterEncoding:(BOOL *)flagp isBycopy:(BOOL)isByCopy
{
if (isByCopy) {
*flagp = NO; // object will copy.
return self; //encode object (copy it)
}
*flagp = NO; // object will copy.
// super will encode the proxy otherwise
return [super encodeRemotelyFor:connection
freeAfterEncoding:flagp isBycopy:isByCopy];
}
- free
{
if (fileOpen) [self closeFile];
[lockFile free];
[fileName free];
return [super free];
}
@end